/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
// #include "bsp_key.h"
#include "bsp_key_irq.h"
#include "bsp_led.h"
#include "print_task_list.h"
#include "log.h"
#include "elog.h"
#include "sample.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */

/* USER CODE END Variables */
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
  .name = "defaultTask",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */

void LED_Task(void *argument);
/* USER CODE END FunctionPrototypes */

void StartDefaultTask(void *argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* creation of defaultTask */
  defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  if ( pdPASS == xTaskCreate(Key_Task, "Key_Task", 128, NULL, osPriorityHigh, NULL) ) {
    log_i("Key_Task Create OK!\r\n");
  } else {
    log_i("Key_Task Create Failed!\r\n");
  }

  if ( pdPASS == xTaskCreate(LED_Task, "LED_Task", 128, NULL, osPriorityNormal, NULL) ) {
    log_i("LED_Task Create OK!\r\n");
  } else {
    log_i("LED_Task Create Failed!\r\n");
  }

  if ( pdPASS == xTaskCreate(Sample_Parse_Task, "Sample_Parse_Task", 128, NULL, osPriorityNormal, &g_sample_parse_task_handle) ) {
    log_i("Sample_Parse_Task Create OK!\r\n");
  } else {
    log_i("Sample_Parse_Task Create Failed!\r\n");
  }

  if ( pdPASS == xTaskCreate(Sample_Task, "Sample_Task", 128, NULL, osPriorityNormal, &g_sample_task_handle) ) {
    log_i("Sample_Task Create OK!\r\n");
  } else {
    log_i("Sample_Task Create Failed!\r\n");
  }


  //printTaskInit();
  /* USER CODE END RTOS_THREADS */

  /* USER CODE BEGIN RTOS_EVENTS */
  /* add events, ... */
  /* USER CODE END RTOS_EVENTS */

}

/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the defaultTask thread.
  * @param  argument: Not used
  * @retval None
  */
int fputc(int ch, FILE *f)
{
	// vTaskSuspendAll();
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
  // xTaskResumeAll();
  return ch;
}
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN StartDefaultTask */
  /* Infinite loop */
  uint32_t       rev_val = 0;
  led_opration_t led_opt = LED_OFF;

#if 0 /* TEST #1 error fetch */
    key_press_event_t key_event = {
      .edge_type    = KEY_TRIGGER_RISING_EDGE,
      .trigger_tick = HAL_GetTick(),
    };
    if ( pdPASS == xQueueSend(inter_key_queue, &key_event, (TickType_t)0) ) 
    {
      printf("Send to inter_key_queue at [%d] tick\r\n", HAL_GetTick());
    }
#endif  /* END TEST #1 error fetch */

#if 0 /* TEST #2 error fetch */
    key_press_event_t key_event = {
      .edge_type    = KEY_TRIGGER_FALLING_EDGE,
      .trigger_tick = HAL_GetTick(),
    };
    if ( pdPASS == xQueueSend(inter_key_queue, &key_event, (TickType_t)0) ) 
    {
      printf("Send to inter_key_queue OK! at [%d] tick\r\n", HAL_GetTick());
    }

    osDelay(100);

    key_event.edge_type    = KEY_TRIGGER_RISING_EDGE;
    key_event.trigger_tick = HAL_GetTick();
    if ( pdPASS == xQueueSend(inter_key_queue, &key_event, (TickType_t)0) ) 
    {
      printf("Send to inter_key_queue OK! at [%d] tick\r\n", HAL_GetTick());
    }
#endif  /* END TEST #2 error fetch */

  for(;;)
  {
    // log_i("StartDefaultTask Running!");
    // LOG_INFO("Hello World! at [%d]\r\n", HAL_GetTick());
    // osDelay(1000);
    // printf("StartDefaultTask Running!\r\n");
    if ( 0 != Key_Queue ) 
    {
      if ( pdPASS == xQueueReceive(Key_Queue, &rev_val, (TickType_t)100) ) 
      {
        printf("Queue rev_val: %d\r\n", rev_val);
        switch (rev_val)
        {
        case KEY_PRESSED:
          // led_opt = LED_TOGGLE;
          led_opt = LED_BLINK;
          if ( pdTRUE == xQueueSend(LED_Queue, &led_opt, (TickType_t)0) ) {
            printf("LED Queue TOGGLE Send OK!\r\n");
          } 
          break;
        case KEY_LONGPRESS:
          // led_opt = LED_BLINK;
          led_opt = LED_BLINK_10_TIMES;
          if ( pdTRUE == xQueueSend(LED_Queue, &led_opt, (TickType_t)0) ) {
            printf("LED Queue BLINK Send OK!\r\n");
          } 
          break;
        case KEY_DOUBLE_PRESSED:
          led_opt = LED_ON;
          printf("LED rev double pressed!\r\n");
          if ( pdTRUE == xQueueSend(LED_Queue, &led_opt, (TickType_t)0) ) {
            printf("LED Queue ON Send OK!\r\n");
          } 
        default:
          break;
        }
      }
    }
    osDelay(100);
  }
  /* USER CODE END StartDefaultTask */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

/* USER CODE END Application */

